home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / daemons / ipServer / route.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-16  |  37.6 KB  |  1,387 lines

  1. /* 
  2.  * route.c --
  3.  *
  4.  *    This file contains routines to handle low-level IP packet I/O and to
  5.  *    maintain information about the network interfaces and packet routing.
  6.  *    Currently, most routines are ethernet-specific.
  7.  *
  8.  *    When an IP packet is to be sent out on the ethernet, the packet's
  9.  *    destination address must be translated to an ethernet address.
  10.  *    This task is called routing and is performed by Rte_FindOutputNet.
  11.  *    The routine uses a static table of <IP, ethernet> entries to map
  12.  *    an IP address into an ethernet address.    The table is initialized
  13.  *    from a file by Rte_AddressInit() and contains entires for hosts on
  14.  *    the ethernet. The IP output routine calls Rte_FindOutputNet to get 
  15.  *    a token (a Rte_NetID structure) that identifies    a route. Along with 
  16.  *    the packet, the route token is passed to Rte_OutputPacket, which uses 
  17.  *    it to insert the ethernet address into the packet. If a corresponding 
  18.  *    ethernet address can't be found for an IP address, it is assumed that 
  19.  *    host is on a different network. In that case, the Rte_NetID token 
  20.  *    identifies a gateway host that can forward the packet to the proper 
  21.  *    network.
  22.  *
  23.  *    (Aside: "Ethernet (capital E) is a specific Xerox protocol used for LAN,
  24.  *      whereas an ethernet (small e) refers to an Ethernet-like network."
  25.  *      Quarterman and Hoskins, CACM v29#10, 10/86, p.938)
  26.  *
  27.  *
  28.  * Copyright 1987 Regents of the University of California
  29.  * All rights reserved.
  30.  * Permission to use, copy, modify, and distribute this
  31.  * software and its documentation for any purpose and without
  32.  * fee is hereby granted, provided that the above copyright
  33.  * notice appear in all copies.  The University of California
  34.  * makes no representations about the suitability of this
  35.  * software for any purpose.  It is provided "as is" without
  36.  * express or implied warranty.
  37.  */
  38.  
  39. #ifndef lint
  40. static char rcsid[] = "$Header: /sprite/src/daemons/ipServer/RCS/route.c,v 1.17 92/06/16 13:03:53 jhh Exp $ SPRITE (Berkeley)";
  41. #endif not lint
  42.  
  43.  
  44. #include "sprite.h"
  45. #include "ipServer.h"
  46. #include "ip.h"
  47. #include "route.h"
  48. #include "stat.h"
  49.  
  50. #ifndef KERNEL
  51. #include <errno.h>
  52. #include <sys/file.h>
  53. #include <host.h>
  54. #endif
  55.  
  56. #include <netEther.h>
  57. #include <list.h>
  58. #include <string.h>
  59. #include <fs.h>
  60. #include <hash.h>
  61.  
  62.  
  63. #ifdef TEST_DISCONNECT
  64. extern int    ips_Disconnect;
  65. #endif
  66. /*
  67.  * Comment character used in the config file. Lines beginning with this
  68.  * character are ignored.
  69.  */
  70. #define COMMENT_CHAR     '#'
  71.  
  72.  
  73. /*
  74.  * Address information kept in a hash table keyed on the internet address.
  75.  * There are a few possibilities for each address
  76.  * NET_NEIGHBOR        The host is a neighbor on the local network
  77.  * NET_GATEWAY        The host is a gateway to other networks
  78.  * NET_ALIAS        This is another alias for ourselves
  79.  * NET_BROADCAST    This is a broadcast address
  80.  * NET_UPDATE_ADDR    Update the physical address information when installing.
  81.  * NET_ETHERNET        The ethernet field has the physical net address.
  82.  */
  83.  
  84. typedef struct NetAddrInfo {
  85.     Net_InetAddress    inet;        /* Hash key, must be first */
  86.     int            flags;        /* NET_NEIGHBOR, NET_GATEWAY,
  87.                      * NET_ALIAS, NET_BROADCAST,
  88.                      * plus type for addr union */
  89.     union {
  90.     Net_EtherAddress ether;        /* NET_ETHERNET */
  91.     } addr;
  92.     struct NetInfo    *netPtr;    /* Interface information */
  93. } NetAddrInfo;
  94.  
  95. /*
  96.  * NET_GATEWAY is also defined to be 0x2 in the kernel's netRoute.h.  Don't
  97.  * change one without the other.  Obviously this should be fixed.
  98.  */
  99. #define NET_NEIGHBOR    0x1
  100. #define NET_GATEWAY    0x2
  101. #define NET_ALIAS    0x4
  102. #define NET_BROADCAST    0x8
  103. #define NET_UPDATE_ADDR    0x10
  104. #define NET_ETHERNET    0x20
  105.  
  106. Hash_Table addrHashTable;
  107. Hash_Table *addrTable = &addrHashTable;
  108.  
  109. #ifdef KERNEL
  110.     /*
  111.      * UGH.  Kernel and user hash packages not the same.
  112.      */
  113. #define Hash_InitTable(table, numBuckets, keys) \
  114.     Hash_Init(table, numBuckets, keys)
  115.  
  116. #define Hash_FindEntry(table, key) \
  117.     Hash_LookOnly(table, key)
  118. #endif
  119.  
  120. /*
  121.  * Information about network interfaces.
  122.  */
  123.  
  124. typedef struct NetInfo {
  125.     char    *name;        /* Device name. */
  126.     int        streamID;    /* Used with Read, Write. */
  127.     int        maxOutputSize;    /* Size in bytes of max. packet size
  128.                  * that this interface can output. */
  129.     int        flags;        /* Defined below. */
  130.     Net_InetAddress address;    /* Official IP address. */
  131.     Net_InetAddress localBrdcastAddr;    /* Broadcast address for the subnet
  132.                      * (directly-connected network). */
  133.     Net_InetAddress netBrdcastAddr;    /* Broadcast address for all subnets
  134.                      * on the logical network. */
  135.     unsigned int netPart;    /* Network number but unshifted. */
  136.     unsigned int netMask;    /* Mask to generate network # from an address.*/
  137.     unsigned int subnetPart;    /* Subnet # (included net #) but unshifted. */
  138.     unsigned int subnetMask;    /* Mask to generate subnet # from an addr. */
  139.  
  140.     NetAddrInfo    *gatewayPtr;    /* The address of the local gateway. */
  141. } NetInfo;
  142.  
  143.  
  144. static NetAddrInfo *localHostAddrPtr;    /* Our own address for loopback. */
  145. /*
  146.  * Values used in the flags field of NetInfo.
  147.  */
  148. #define NET_IN_USE    0x1
  149.  
  150.  
  151. #define MAX_NUM_NETS    4
  152. static NetInfo    netInfo[MAX_NUM_NETS];
  153. static int    numNetInterfaces = 0;
  154.  
  155. /*
  156.  * IP Address to look for route to.  When IPInput sees this address come
  157.  * by it snarfs up the source ethernet address.  The localhost value will
  158.  * never arrive as input, so it is the "do nothing" value.
  159.  */
  160. static Net_InetAddress lookforIPAddress = NET_INET_LOCAL_HOST;
  161. /*
  162.  * Forward declaration of internal procedures.
  163.  */
  164. NetAddrInfo *RteInsertAddress();
  165. NetAddrInfo *RteFetchAddress();
  166.  
  167. static void ReadIPPacket();
  168. static void GetLineList();
  169. static Net_EtherAddress broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  170.  
  171.  
  172.  
  173.  
  174. /*
  175.  *----------------------------------------------------------------------
  176.  *
  177.  * Rte_AddressInit --
  178.  *
  179.  *    Reads a file that contains the following information: 
  180.  *    1) the name of IP network device,
  181.  *    2) a bit mask used to generate a host number for hosts on the same
  182.  *       network (subnet mask).
  183.  *    3) the maximum # of bytes the network device can output.
  184.  *    4) a list of alias IP addresses for this program. Packets sent
  185.  *       to one of these addresses will be handled.
  186.  *    5) a name of a gateway for the network. 
  187.  *    Host Internet and ethernet addresses are obtained from 
  188.  *    /etc/spritehosts. This information is used to initialize 
  189.  *    the network and neighbor information tables.
  190.  *
  191.  *    To do: extend to multiple networks.
  192.  *
  193.  * Kernel Implementation:
  194.  *    This doesn't read the configuration file when running in the kernel.
  195.  *    Instead the Net_RouteInstall system uses RteInsertAddress to
  196.  *    give us addressing information.  This just sets up the net stucture
  197.  *    and installs the various broadcast addresses that map to it.
  198.  *
  199.  * Results:
  200.  *    None.
  201.  *
  202.  * Side effects:
  203.  *    The network table is initialized.  There is both a per-interface
  204.  *    structure and a hash table of internet addresses.  Addresses
  205.  *    are installed for our own aliases, for our local neighbors,
  206.  *    for the gateway, and for various broadcast addresses.
  207.  *
  208.  *----------------------------------------------------------------------
  209.  */
  210.  
  211. void
  212. Rte_AddressInit(myHostName, filename, newOfficialAddr)
  213.     char *myHostName;
  214.     char *filename;        /* Name of configuration file. */
  215.     char *newOfficialAddr;    /* If not NULL, use this as the official 
  216.                  * IP address. */
  217. {
  218. #ifndef KERNEL
  219.     /*
  220.      * Only the user-level version reads the config file.
  221.      * The kernel gets routing information via the Net_Route system call.
  222.      */
  223.  
  224. #define LINE_LEN    80
  225. #define ARRAY_SIZE    100
  226.  
  227.     FILE        *stream;
  228.     char        *array[ARRAY_SIZE];
  229.     int            numGateways;
  230.     int            numAliases;
  231.     char        devName[LINE_LEN];
  232.     char        etherString[LINE_LEN];
  233.     char        inetString[LINE_LEN];
  234.     char        line[LINE_LEN];
  235.     char        host[LINE_LEN];
  236.     Host_Entry         *hostPtr;
  237. #endif
  238.     Net_InetAddress    address;
  239.     Net_EtherAddress    etherAddr;
  240.     NetAddrInfo        *addrPtr;
  241.     Boolean        foundOfficialAddr = FALSE;
  242.     register NetInfo    *infoPtr;
  243.     int            i;
  244.     int            numHosts;
  245.     unsigned int    subpart;
  246.  
  247. #ifndef KERNEL
  248.     stream = fopen(filename, "r");
  249.     if (stream == (FILE *) NULL) {
  250.     (void) fprintf(stderr, "Can't open net info file '%s'\n", filename);
  251.     exit(1);
  252.     }
  253. #endif
  254.  
  255.     /*
  256.      * For now, assume just one net in the netinfo file.
  257.      */
  258.  
  259.     infoPtr = &netInfo[0];
  260.  
  261. #ifndef KERNEL
  262.     do {
  263.     (void) fgets(line, LINE_LEN, stream);
  264.     } while (line[0] == COMMENT_CHAR);
  265.  
  266.     /*
  267.      * Look for the config file version and print it if debug is set.
  268.      */
  269.  
  270.     if (strncmp("version", line, strlen("version")) != 0) {
  271.     (void) fprintf(stderr, "Bad format in %s: version.\n", filename);
  272.     exit(1);
  273.     }
  274.     (void) printf("Config file: %s\n   %s\n", filename, line);
  275.  
  276.  
  277.     /*
  278.      ***********************************************************************
  279.      *
  280.      * Group 1:  network device name, subnet mask,
  281.      *         max. # bytes output on the network device.
  282.      *    Example: /dev/etherIP    0xffffff00      1500
  283.      *
  284.      ***********************************************************************
  285.      */
  286.  
  287.     do {
  288.     (void) fgets(line, LINE_LEN, stream);
  289.     } while (line[0] == COMMENT_CHAR);
  290.  
  291.     i = sscanf(line, "%s 0x%x %d", devName, &infoPtr->subnetMask, 
  292.             &infoPtr->maxOutputSize);
  293.     if (i != 3) {
  294.     panic("Bad format in %s: device name.\n", filename);
  295.     }
  296.  
  297.     infoPtr->streamID = open(devName, O_RDWR | O_NDELAY , 0); 
  298.     if (infoPtr->streamID < 0) {
  299.     perror("Rte_AddressInit (open net)");
  300.     exit(1);
  301.     }
  302.  
  303.     /*
  304.      * Tell the dispatcher we're interested when packets arrive on
  305.      * this stream.
  306.      */
  307.     Fs_EventHandlerCreate(infoPtr->streamID, FS_READABLE, ReadIPPacket, 
  308.             (ClientData) 0);
  309.  
  310.     infoPtr->name = malloc((unsigned int) strlen(devName) + 1);
  311.     (void) strcpy(infoPtr->name, devName);
  312. #endif
  313.  
  314.     infoPtr->flags        |= NET_IN_USE;
  315.  
  316.     /*
  317.      * Initialize the address table and insert our official address.
  318.      */
  319.     Hash_InitTable(addrTable, 64, HASH_ONE_WORD_KEYS);
  320.  
  321.     if (newOfficialAddr != (char *) NULL) {
  322.     infoPtr->address = 
  323.         Net_NetToHostInt(Net_StringToInetAddr(newOfficialAddr));
  324.     foundOfficialAddr = TRUE;
  325.     (void)RteInsertAddress(infoPtr->address, (Net_EtherAddress *)NULL,
  326.         NET_ALIAS, infoPtr);
  327.     }
  328.  
  329.     /*
  330.      ***********************************************************************
  331.      *
  332.      * Group 2:  List of aliases for this machine.
  333.      *         Format:  <name> <inet address>
  334.      *       Delimited by "Start_Aliases" and "End_Aliases"
  335.      *
  336.      ***********************************************************************
  337.      */
  338. #ifndef KERNEL
  339.     GetLineList(stream, "Start_Aliases", "End_Aliases", ARRAY_SIZE, array, 
  340.         &numAliases);
  341.     for (i = 0; i < numAliases; i++) {
  342.     (void) sscanf(array[i], "%s %s", host, inetString);
  343.     address = Net_NetToHostInt(Net_StringToInetAddr(inetString));
  344.     (void)RteInsertAddress(address, (Net_EtherAddress *)NULL, NET_ALIAS,
  345.         infoPtr);
  346.     free(array[i]);
  347.     }
  348. #endif
  349.     /*
  350.      ************************************************************************
  351.      *
  352.      * Read /etc/spritehosts to get local host (neighbor) information
  353.      *
  354.      ************************************************************************
  355.      */
  356. #ifndef KERNEL
  357.     if (!foundOfficialAddr) {
  358.     hostPtr = Host_ByName(myHostName);
  359.     if (hostPtr != NULL) {
  360.         /*
  361.          * Look for the ethernet interface and get its internet address.
  362.          * TODO: in reality the physical address for the interface
  363.          * should be obtained via an ioctl on the open device. This
  364.          * address would then be used to determine the internet address
  365.          * for the interface, and which hosts are local as well.
  366.          */
  367.         for (i = 0; i < hostPtr->numNets; i++) {
  368.         if (hostPtr->nets[i].netAddr.type == NET_ADDRESS_ETHER) {
  369.             infoPtr->address = 
  370.             Net_NetToHostInt(hostPtr->nets[i].inetAddr);
  371.             foundOfficialAddr = TRUE;
  372.         }
  373.         }
  374.     } else {
  375.         panic("Rte_AddressInit: could not find myself in the host file\n");
  376.     }
  377.     }
  378.     if (!foundOfficialAddr) {
  379.     panic("Rte_AddressInit: can't find IP address for %s\n", myHostName);
  380.     }
  381.     subpart = infoPtr->subnetMask & infoPtr->address;
  382.     if (Host_Start() != SUCCESS) {
  383.     panic("Rte_AddressInit: Host_Start failed (?no /etc/spritehosts?)\n");
  384.     }
  385.     for (hostPtr = Host_Next();
  386.          hostPtr != (Host_Entry *)NULL;
  387.      hostPtr = Host_Next()) {
  388.     register int flags;
  389.  
  390.     flags = NET_NEIGHBOR;
  391.     for (i = 0; i < hostPtr->numNets; i++) {
  392.         /*
  393.          * Only install the route if the interfaces are on the same 
  394.          * subnet. We assume that a host will have only one interface
  395.          * on the same subnet.
  396.          */
  397.         address = Net_NetToHostInt(hostPtr->nets[i].inetAddr);
  398.         if ((infoPtr->subnetMask & address) == subpart) {
  399.         if (address == infoPtr->address) {
  400.             flags |= NET_ALIAS;
  401.         }
  402.         (void)RteInsertAddress(address, 
  403.             &hostPtr->nets[i].netAddr.address.ether, 
  404.             flags, infoPtr);
  405.         break;
  406.         }
  407.     }
  408.     }
  409.     Host_End();
  410.  
  411. #endif /* not KERNEL */
  412.  
  413.     /*
  414.      * Now that we know our own ethernet address we add the "localhost"
  415.      * address that points back to ourself.
  416.      */
  417.     addrPtr = RteFetchAddress(infoPtr->address);
  418.     if ((addrPtr != (NetAddrInfo *)NULL) && (addrPtr->flags & NET_ETHERNET)) {
  419.     (void)RteInsertAddress(NET_INET_LOCAL_HOST, &addrPtr->addr.ether,
  420.         NET_ALIAS|NET_UPDATE_ADDR, infoPtr);
  421.     }
  422.     /*
  423.      ***********************************************************************
  424.      *
  425.      * Group 3: Gateway info
  426.      *        Format:  <name> <ip-addr> <ether-addr>
  427.      *         Delimited by "Start_Gateways" and "End_Gateways"
  428.      *
  429.      *     Assume just 1 gateway for now.
  430.      *
  431.      ***********************************************************************
  432.      */
  433. #ifndef KERNEL
  434.     GetLineList(stream, "Start_Gateways", "End_Gateways", ARRAY_SIZE, array,
  435.         &numGateways);
  436.     if (numGateways == 0) {
  437.     panic("Rte_AddressInit: can't find gateway name in '%s'\n", filename);
  438.     }
  439.     for (i=0 ; i<numGateways ; i++) {
  440.     (void) sscanf(array[i], "%s %s %s", host, inetString, etherString);
  441.     address = Net_NetToHostInt(Net_StringToInetAddr(inetString));  
  442.     Net_StringToEtherAddr(etherString, ðerAddr);
  443.     infoPtr->gatewayPtr = RteInsertAddress(address, ðerAddr,
  444.                 NET_NEIGHBOR|NET_GATEWAY, infoPtr);
  445.     free(array[i]);
  446.     }
  447. #endif
  448.     /*
  449.      * Note our address and the various pieces of it for sub-netting.
  450.      */
  451.  
  452.     address            = infoPtr->address;
  453.     infoPtr->netMask        = Net_InetAddrNetMask(address);
  454.     infoPtr->netPart        = infoPtr->netMask & address;
  455.     infoPtr->subnetMask        |= infoPtr->netMask;
  456.     infoPtr->subnetPart        = infoPtr->subnetMask & address;
  457.  
  458.     infoPtr->localBrdcastAddr    = (infoPtr->subnetPart | 
  459.                 (NET_INET_BROADCAST_ADDR & ~infoPtr->subnetMask));
  460.  
  461.     infoPtr->netBrdcastAddr    = (infoPtr->netPart |
  462.                 (NET_INET_BROADCAST_ADDR & ~infoPtr->netMask));
  463.  
  464.     /*
  465.      * Install various BROADCAST addresses that we should accept.
  466.      * The old-style broadcast address uses a host part of 0, hence
  467.      * the use of the (sub)netPart values.
  468.      */
  469.     (void)RteInsertAddress(NET_INET_BROADCAST_ADDR, &broadcast,
  470.                 NET_BROADCAST, infoPtr);
  471.     (void)RteInsertAddress(NET_INET_ANY_ADDR, (Net_EtherAddress *)NULL,
  472.                 NET_BROADCAST, infoPtr);
  473.     (void)RteInsertAddress(infoPtr->localBrdcastAddr, &broadcast,
  474.                 NET_BROADCAST, infoPtr);
  475.     (void)RteInsertAddress(infoPtr->netBrdcastAddr, &broadcast,
  476.                 NET_BROADCAST, infoPtr);
  477.     (void)RteInsertAddress(infoPtr->subnetPart, (Net_EtherAddress *)NULL,
  478.                 NET_BROADCAST, infoPtr);
  479.     (void)RteInsertAddress(infoPtr->netPart, (Net_EtherAddress *)NULL,
  480.                 NET_BROADCAST, infoPtr);
  481.  
  482. #ifndef KERNEL
  483.     if (ips_Debug) {
  484.     (void) fprintf(stderr, "Host name = %s\n", myHostName);
  485.     (void) fprintf(stderr, "Official address = %s\n", 
  486.             Net_InetAddrToString(infoPtr->address, line));
  487.     (void) fprintf(stderr, "Local broadcast address = %s\n",
  488.             Net_InetAddrToString(infoPtr->localBrdcastAddr, line));
  489.     (void) fprintf(stderr, "Net broadcast address = %s\n",
  490.             Net_InetAddrToString(infoPtr->netBrdcastAddr, line));
  491.     }
  492. #endif
  493.  
  494.     numNetInterfaces++;
  495. }
  496.  
  497.  
  498. /*
  499.  *----------------------------------------------------------------------
  500.  *
  501.  * RteInsertAddress --
  502.  *
  503.  *    Allocate and insert an address entry in the table.  This can be
  504.  *    used to update the ethernet address for an existing entry.
  505.  *
  506.  * Results:
  507.  *    None.
  508.  *
  509.  * Side effects:
  510.  *    Allocate and insert an address entry in the table.
  511.  *
  512.  *----------------------------------------------------------------------
  513.  */
  514.  
  515. NetAddrInfo *
  516. RteInsertAddress(inet, etherPtr, flags, netPtr)
  517.     Net_InetAddress inet;        /* Internet address, the address KEY */
  518.     Net_EtherAddress *etherPtr;        /* Ethernet address, or NULL */
  519.     int flags;                /* NET_NEIGHBOR, NET_GATEWAY, NET_ALIAS,
  520.                      * NET_BROADCAST, NET_UPDATE_ADDR */
  521.     NetInfo *netPtr;            /* Pointer to interface info */
  522. {
  523.     register NetAddrInfo *addrPtr;
  524.     register Hash_Entry *hashEntryPtr;
  525.     int created;
  526.  
  527. #ifdef KERNEL
  528.     if (netPtr == (NetInfo *)NIL) {
  529.     netPtr = &netInfo[0];
  530.     }
  531.     if (etherPtr == (Net_EtherAddress *)NIL) {
  532.     etherPtr = (Net_EtherAddress *)NULL;
  533.     }
  534.     hashEntryPtr = Hash_Find(addrTable, inet);
  535.     addrPtr = (NetAddrInfo *)Hash_GetValue(hashEntryPtr);
  536.     if (addrPtr == (NetAddrInfo *)NIL) {
  537.     created = TRUE;
  538.     }
  539. #else
  540.     hashEntryPtr = Hash_CreateEntry(addrTable, inet, &created);
  541. #endif
  542.     if (created) {
  543.     addrPtr = (NetAddrInfo *)malloc(sizeof(NetAddrInfo));
  544.     addrPtr->inet = inet;
  545.     addrPtr->flags = flags & ~NET_ETHERNET;
  546.     addrPtr->netPtr = netPtr;
  547.     Hash_SetValue(hashEntryPtr, addrPtr);
  548.     } else {
  549.     addrPtr = (NetAddrInfo *)Hash_GetValue(hashEntryPtr);
  550.     }
  551.     /*
  552.      * Update the ethernet address if we are told to, or if we are given
  553.      * an address and we don't already have one.
  554.      */
  555.     if ((((addrPtr->flags & NET_ETHERNET) == 0) || (flags & NET_UPDATE_ADDR)) &&
  556.     (etherPtr != (Net_EtherAddress *)NULL)) {
  557.     NET_ETHER_ADDR_COPY(*etherPtr, addrPtr->addr.ether);
  558.     addrPtr->flags |= NET_ETHERNET;
  559.     }
  560.     return(addrPtr);
  561. }
  562.  
  563.  
  564. /*
  565.  *----------------------------------------------------------------------
  566.  *
  567.  * RteFetchAddress --
  568.  *
  569.  *    Fetch an address entry from the table.
  570.  *
  571.  * Results:
  572.  *    NULL, or a pointer to the address information.
  573.  *
  574.  * Side effects:
  575.  *    None.
  576.  *
  577.  *----------------------------------------------------------------------
  578.  */
  579.  
  580. NetAddrInfo *
  581. RteFetchAddress(inet)
  582.     Net_InetAddress inet;        /* Internet address, the address KEY */
  583. {
  584.     register NetAddrInfo *addrPtr;
  585.     register Hash_Entry *hashEntryPtr;
  586.  
  587.     hashEntryPtr = Hash_FindEntry(addrTable, inet);
  588.     if (hashEntryPtr != (Hash_Entry *)NULL) {
  589.     addrPtr = (NetAddrInfo *)Hash_GetValue(hashEntryPtr);
  590.     return(addrPtr);
  591.     }
  592.     return((NetAddrInfo *)NULL);
  593. }
  594.  
  595.  
  596. /*
  597.  *----------------------------------------------------------------------
  598.  *
  599.  * Rte_AddrIsForUs --
  600.  *
  601.  *    Returns TRUE if the specified address can be used to name 
  602.  *    this server. The address is checked to see if it's a broadcast
  603.  *    address and if not, it is compared with official and alias
  604.  *    IP addresses for this server.
  605.  *
  606.  * Results:
  607.  *    TRUE    - the address is for us.
  608.  *    FALSE    - the address is not for us.
  609.  *
  610.  * Side effects:
  611.  *    None.
  612.  *
  613.  *----------------------------------------------------------------------
  614.  */
  615.  
  616. Boolean
  617. Rte_AddrIsForUs(addr)
  618.     Net_InetAddress    addr;
  619. {
  620.     register NetAddrInfo *addrPtr;
  621.  
  622.     addr = Net_NetToHostInt(addr);
  623.     addrPtr = RteFetchAddress(addr);
  624.  
  625.     if ((addrPtr != (NetAddrInfo *)0) &&
  626.     (addrPtr->flags & (NET_BROADCAST|NET_ALIAS))) {
  627.     return(TRUE);
  628.     }
  629.     return(FALSE);
  630. }
  631.  
  632.  
  633. /*
  634.  *----------------------------------------------------------------------
  635.  *
  636.  * Rte_ValidateAddress --
  637.  *
  638.  *    This routine returns TRUE if the specified address corresponds
  639.  *    to one of the addresses (official or alias) of this server.
  640.  *    The address has to be an exact match -- that is it can't be
  641.  *    a broadcast address.
  642.  *
  643.  * Results:
  644.  *    TRUE    - the address is a valid for this server.
  645.  *    FALSE    - the address doesn't match one of the server's addresses.
  646.  *
  647.  * Side effects:
  648.  *    None.
  649.  *
  650.  *----------------------------------------------------------------------
  651.  */
  652.  
  653. Boolean
  654. Rte_ValidateAddress(addr)
  655.     Net_InetAddress    addr;
  656. {
  657.     register NetAddrInfo *addrPtr;
  658.  
  659.     addr = Net_NetToHostInt(addr);
  660.     addrPtr = RteFetchAddress(addr);
  661.  
  662.     if ((addrPtr != (NetAddrInfo *)0) && (addrPtr->flags & NET_ALIAS)) {
  663.     return(TRUE);
  664.     }
  665.     return(FALSE);
  666. }
  667.  
  668.  
  669.  
  670. /*
  671.  *----------------------------------------------------------------------
  672.  *
  673.  * Rte_FindOutputNet --
  674.  *
  675.  *    This routine determines the network interface to use when sending
  676.  *    an IP datagram to the given destination (i.e. address routing).
  677.  *    The caller is given a netID to pass to Rte_OutputPacket routine
  678.  *    that contains the required addressing info.
  679.  *
  680.  *    For the time being, a very simple routing method is used: if the 
  681.  *    destination address is on the same network, and we have an ethernet 
  682.  *    address for it, then the datagram can be sent directly. In all other 
  683.  *    cases, a Unix gateway machine is chosen to receive the datagram.
  684.  *
  685.  *    In the future, this routine should 1) use the address resolution
  686.  *    protocol to find ethernet addresses of directly-connected hosts
  687.  *    and 2) use a routing tables to do proper routing when there's more
  688.  *    than 1 gateway.
  689.  *
  690.  * Results:
  691.  *    TRUE        - a route was found.
  692.  *    FALSE        - no route could be found for the address.
  693.  *
  694.  * Side effects:
  695.  *    None.
  696.  *
  697.  *----------------------------------------------------------------------
  698.  */
  699.  
  700. Boolean
  701. Rte_FindOutputNet(dest, netIDPtr, maxOutSizePtr)
  702.     Net_InetAddress    dest;
  703.     register Rte_NetID    *netIDPtr;
  704.     int            *maxOutSizePtr;
  705. {
  706.     register NetInfo    *infoPtr;
  707.     register NetAddrInfo *addrPtr;
  708.  
  709. #ifdef notdef
  710.     static Net_InetAddress    prevDest;
  711.     static Rte_NetID        prevID;
  712.     static int            prevOutSize = -1;
  713. #endif notdef
  714.  
  715.     dest = Net_NetToHostInt(dest);
  716.     stats.misc.routeCalls++;
  717.  
  718.     /*
  719.      * If the destination is the same as the one in the last call,
  720.      * return the same information.
  721.      */
  722. #ifdef notdef
  723.     if (dest == prevDest && prevOutSize != -1) {
  724.     *netIDPtr = prevID;
  725.     *maxOutSizePtr = prevOutSize;
  726.     stats.misc.routeCacheHits++;
  727.     return(TRUE);
  728.     }
  729. #endif notdef
  730.  
  731.     addrPtr = RteFetchAddress(dest);
  732.     if (addrPtr == (NetAddrInfo *)NULL) {
  733.     if (ips_Debug) {
  734.         fprintf(stderr, "RteFindOutputNet: !found, inserting gateways\n");
  735.     }
  736.     /*
  737.      * No address found.  Create an entry with the physical address
  738.      * of the gateway.  When we get a redirect ICMP then we save
  739.      * the physical address.  This uses a hack in IPInput
  740.      * to grab the ethernet source address of packets from lookforIPAddress.
  741.      */
  742.     infoPtr = &netInfo[0];
  743.     addrPtr = RteInsertAddress(dest, &infoPtr->gatewayPtr->addr.ether,
  744.             0, infoPtr);
  745.     lookforIPAddress = dest;
  746.     } else if (ips_Debug) {
  747.     fprintf(stderr, "RteFindOutputNet: (%x:%x:%x:%x:%x:%x)\n",
  748.         (unsigned char)NET_ETHER_ADDR_BYTE1(addrPtr->addr.ether),
  749.         (unsigned char)NET_ETHER_ADDR_BYTE2(addrPtr->addr.ether),
  750.         (unsigned char)NET_ETHER_ADDR_BYTE3(addrPtr->addr.ether),
  751.         (unsigned char)NET_ETHER_ADDR_BYTE4(addrPtr->addr.ether),
  752.         (unsigned char)NET_ETHER_ADDR_BYTE5(addrPtr->addr.ether),
  753.         (unsigned char)NET_ETHER_ADDR_BYTE6(addrPtr->addr.ether));
  754.     }
  755.     netIDPtr->net = (int)addrPtr->netPtr;
  756.     netIDPtr->host = (int)addrPtr;
  757.     *maxOutSizePtr = addrPtr->netPtr->maxOutputSize;
  758.  
  759. found:
  760. #ifdef notdef
  761.     prevID = *netIDPtr;
  762.     prevDest = dest;
  763.     prevOutSize = *maxOutSizePtr;
  764. #endif notdef
  765.     return(TRUE);
  766. }
  767.  
  768.  
  769.  
  770. /*
  771.  *----------------------------------------------------------------------
  772.  *
  773.  * Rte_UpdateRoute --
  774.  *
  775.  *    Update a route.  This tells IPInput to look for the 'useAddr'
  776.  *    so we can get a good ethernet address for it.
  777.  *     
  778.  *
  779.  * Results:
  780.  *    None.
  781.  *
  782.  * Side effects:
  783.  *    
  784.  *
  785.  *----------------------------------------------------------------------
  786.  */
  787.  
  788. int
  789. Rte_UpdateRoute(toAddr, useAddr)
  790.     Net_InetAddress    toAddr;    /* What we were using.  */
  791.     Net_InetAddress    useAddr;    /* What we should use. */
  792. {
  793.  
  794.         register NetInfo    *infoPtr;
  795.     int            i;
  796.  
  797.     for (i=0; i < numNetInterfaces; i++) {
  798.     infoPtr = &netInfo[i];
  799.     if ((infoPtr->subnetMask & toAddr) == infoPtr->subnetPart) {
  800.         /*
  801.          * The address is for our subnet.
  802.          */
  803.         lookforIPAddress = toAddr;
  804.     }
  805.     }
  806.     return (0);
  807.  
  808. }
  809.  
  810.  
  811.  
  812.  
  813. /*
  814.  *----------------------------------------------------------------------
  815.  *
  816.  * Rte_OutputPacket --
  817.  *
  818.  *    Sends an IP packet on the network. The ethernet header is
  819.  *    formatted to send the packet to the given destination. The
  820.  *    packet type is set to the IP type value.
  821.  *        
  822.  *    This routine only works for ethernets. 
  823.  *
  824.  * Results:
  825.  *    SUCCESS     - the packet was sent.
  826.  *    FAILURE        - the write failed.
  827.  *
  828.  * Side effects:
  829.  *    A packet is sent out on the wire.
  830.  *
  831.  *----------------------------------------------------------------------
  832.  */
  833.  
  834. ReturnStatus
  835. Rte_OutputPacket(netID, packetPtr)
  836.     Rte_NetID    netID;
  837.     register IPS_Packet    *packetPtr;
  838. {
  839.     register NetInfo    *infoPtr;
  840.     register NetAddrInfo *addrPtr;
  841.     ReturnStatus    status;
  842.     int            numWritten;
  843.     int            len;
  844. #ifdef KERNEL
  845.     Net_ScatterGather    ioVector;
  846. #endif
  847.  
  848.     infoPtr = (NetInfo *)netID.net;
  849.     addrPtr = (NetAddrInfo *)netID.host;
  850.  
  851.     if ((addrPtr->flags & NET_ETHERNET) == 0) {
  852.     /*
  853.      * We don't have an ethernet address for this guy.
  854.      */
  855.     return(FAILURE);
  856.     }
  857.  
  858.     packetPtr->net.etherPtr = (Net_EtherHdr *)(((Address) packetPtr->ipPtr) - 
  859.                     sizeof(*packetPtr->net.etherPtr));
  860.     NET_ETHER_HDR_TYPE(*(packetPtr->net.etherPtr)) = Net_HostToNetShort(NET_ETHER_IP);
  861.     NET_ETHER_ADDR_COPY(addrPtr->addr.ether,
  862.             NET_ETHER_HDR_DESTINATION(*(packetPtr->net.etherPtr)));
  863.  
  864.     len = packetPtr->ipLen + packetPtr->hdrLen + packetPtr->dataLen;
  865.  
  866.     if (len > infoPtr->maxOutputSize) {
  867.     panic(
  868.     "Rte_OutputPacket: tried to send too much: ip = %d, hdr = %d, data= %d\n",
  869.             packetPtr->ipLen, packetPtr->hdrLen, packetPtr->dataLen);
  870.     return(FAILURE);
  871.     }
  872.             
  873.     if (ips_Debug) {
  874.     (void) fprintf(stderr, "Rte_OutputPacket: %d\n", len);
  875.     }
  876.  
  877. #ifdef TEST_RANDOM_OUTPUT_LOST
  878.     if ((random()&0x1) == 0) {
  879.     printf("Losing a output packet\n");
  880.     return(SUCCESS);
  881.     }
  882. #endif
  883.  
  884. #ifdef TEST_DISCONNECT
  885.  
  886.     if (ips_Disconnect) {
  887.         printf("Losing a output packet\n");
  888.         return(SUCCESS);
  889.     }
  890. #endif
  891.  
  892. #ifdef KERNEL
  893.     /*
  894.      * Call the network output routine.   By now the packet has been assembled
  895.      * contiguously.  However, we have separate pointers to the ethernet
  896.      * header and the IP header that follows immediately.
  897.      */
  898.     ioVector.bufAddr     = (Address)packetPtr->ipPtr;
  899.     ioVector.length    = len;
  900.  
  901.     Net_EtherOutputSync(packetPtr->net.etherPtr, &ioVector, 1);
  902.     numWritten = len;
  903.     status = SUCCESS;
  904. #else
  905.     /*
  906.      * Write the packet to the network device file.
  907.      */
  908.     len += sizeof(*packetPtr->net.etherPtr);
  909.     numWritten = write(infoPtr->streamID, (Address)packetPtr->net.etherPtr,len);
  910.     status = (numWritten == len) ? SUCCESS : FAILURE; 
  911.     if (status != SUCCESS) {
  912.         perror("Rte_OutputPacket");
  913.     }
  914.     if (numWritten != len) {
  915.     (void) fprintf(stderr, 
  916.     "Rte_OutputPacket: write failed: num written (%d) != len (%d)\n",
  917.         numWritten, len);
  918.     }
  919. #endif
  920.     return(status);
  921. }
  922.  
  923.  
  924. /*
  925.  *----------------------------------------------------------------------
  926.  *
  927.  * ReadIPPacket --
  928.  *
  929.  *    Reads one or more packets from the IP network device and passes them
  930.  *    to the IP input routine. Called from the FS dispatcher.
  931.  *
  932.  * Results:
  933.  *    None.
  934.  *
  935.  * Side effects:
  936.  *    Allocates memory which might not be deallocated immediately.
  937.  *    If the incomming address is lookforIPAddress we update the
  938.  *    routing information for it.
  939.  *
  940.  *----------------------------------------------------------------------
  941.  */
  942.  
  943. #ifndef KERNEL
  944.  
  945. /*ARGSUSED*/
  946. static void
  947. ReadIPPacket(data, streamID, eventMask)
  948.     ClientData    data;            /* Network interface number. */
  949.     int        streamID;        /* ID of stream that became readable.*/
  950.     int        eventMask;        /* Mask to show what event happened.
  951.                      * Must be FS_READABLE. */
  952. {
  953.     Rte_NetID        netID;
  954.     int            amtRead;
  955.     int            bufLen = NET_ETHER_MAX_BYTES;
  956.     Boolean        reusePacket = FALSE;
  957.     int            packets = 0;
  958.     NetInfo        *infoPtr;
  959.     NetAddrInfo        *addrPtr;
  960.     IPS_Packet        packet;
  961.  
  962. #define MAX_PACKETS    4
  963.  
  964.     infoPtr = &netInfo[(int)data];
  965.     while (packets < MAX_PACKETS) {
  966.     packets++;
  967.     netID.net = (int)infoPtr;
  968.     netID.host = -1;
  969.     
  970.     /*
  971.      * We have to allocate a buffer from the heap and not from the
  972.      * stack because the IP routine may need to hang on to it after this
  973.      * routine returns. To make the SPUR happy, we insure that the ethernet
  974.      * header starts on a short-word boundry.
  975.      */
  976.     
  977.     bufLen = NET_ETHER_MAX_BYTES;
  978.     
  979.     if (!reusePacket) {
  980.         packet.base = malloc((unsigned int) bufLen + 2);
  981.         packet.dbase = packet.base+2;
  982.         reusePacket = TRUE;
  983.     }
  984.     
  985.     amtRead = read(streamID, packet.dbase, bufLen);
  986.     if (amtRead < 0) {
  987.         if (errno == EWOULDBLOCK) {
  988.         break;
  989.         } else {
  990.         perror("ReadIPPacket (Fs_Read)");
  991.         exit(1);
  992.         }
  993.     }
  994.     if (amtRead <= 0) {
  995.         panic("ReadIPPacket: EOF reading network");
  996.     }
  997.  
  998.     packet.totalLen  = amtRead;
  999.     packet.ipLen = amtRead - sizeof(*packet.net.etherPtr);
  1000.     packet.ipPtr = (Net_IPHeader *) (packet.dbase + sizeof(*packet.net.etherPtr));
  1001.     
  1002. #ifdef TEST_RANDOM_INPUT_LOST
  1003.     if ((random()&0x1) == 0) {
  1004.         fprintf(stderr, "Losing an input packet\n");
  1005.         continue;
  1006.     }
  1007. #endif
  1008. #ifdef TEST_DISCONNECT
  1009.        if (ips_Disconnect) {
  1010.         printf(stderr, "Losing an input packet\n");
  1011.         continue;
  1012.     }
  1013. #endif
  1014.     /*
  1015.      * PRIMITIVE ROUTING.  Snarf up the ethernet source address of
  1016.      * packets comming from hosts (1) that we want to know about.
  1017.      */
  1018.     if (Net_NetToHostInt(packet.ipPtr->source) == lookforIPAddress) {
  1019.         RteInsertAddress(lookforIPAddress,
  1020.         NET_ETHER_HDR_SOURCE_PTR(*(Net_EtherHdr *) packet.dbase),
  1021.         NET_UPDATE_ADDR, infoPtr);
  1022.         lookforIPAddress = NET_INET_LOCAL_HOST;
  1023.     }
  1024.     
  1025.     if (IP_Input(netID, &packet) == SUCCESS) {
  1026.         reusePacket = FALSE;
  1027.     } else {
  1028.         reusePacket = TRUE;;
  1029.     }
  1030.     }
  1031.     if (reusePacket) {
  1032.     free(packet.base);
  1033.     }
  1034. }
  1035. #endif /* not KERNEL */
  1036.  
  1037.  
  1038. /*
  1039.  *----------------------------------------------------------------------
  1040.  *
  1041.  * IP_PacketInput --
  1042.  *
  1043.  *    Called to take a packet off the input queue.  We are called
  1044.  *    via a Proc_CallFunc initiated from interrupt handler.
  1045.  *
  1046.  * Results:
  1047.  *    None.
  1048.  *
  1049.  * Side effects:
  1050.  *    Allocates memory which might not be deallocated immediately.
  1051.  *    If the incomming address is lookforIPAddress we update the
  1052.  *    routing information for it.
  1053.  *
  1054.  *----------------------------------------------------------------------
  1055.  */
  1056.  
  1057. #ifdef KERNEL
  1058.  
  1059. /*ARGSUSED*/
  1060. void
  1061. IP_PacketInput(protoPtr, callInfoPtr)
  1062.     ClientData protoPtr;
  1063.     Proc_CallInfo *callInfoPtr;
  1064. {
  1065.     Rte_NetID        netID;
  1066.     NetInfo        *infoPtr;
  1067.     NetAddrInfo        *addrPtr;
  1068.     Fs_Device        device;
  1069.     IPS_Packet        packet;
  1070.     int            amtRead;
  1071.     ReturnStatus    status;
  1072.  
  1073.     infoPtr = &netInfo[0];
  1074.     netID.net = (int)infoPtr;
  1075.     netID.host = -1;
  1076.     
  1077.     /*
  1078.      * We have to allocate a buffer from the heap and not from the
  1079.      * stack because the IP routine may need to hang on to it after this
  1080.      * routine returns. To make the SPUR happy, we insure that the ethernet
  1081.      * header (dbase) starts on a short word boundary causing the rest of
  1082.      * the packet to be word aligned.
  1083.      */
  1084.  
  1085.     amtRead = NET_ETHER_MAX_BYTES;
  1086.     
  1087.     packet.base = malloc((unsigned int) amtRead + 2);
  1088.     packet.dbase = packet.base+2;
  1089.  
  1090.     /*
  1091.      * Fake a Fs_Device structure and pass it to DevNet_FsRead to
  1092.      * get the packet off of the input queue.
  1093.      */
  1094.     device.data = protoPtr;
  1095.     status = DevNet_FsRead(&device, 0, amtRead, packet.dbase, &amtRead);
  1096.     if (status != SUCCESS) {
  1097.     goto exit;
  1098.     }
  1099.  
  1100.     packet.totalLen  = amtRead;
  1101.     packet.ipLen = amtRead - sizeof(*packet.net.etherPtr);
  1102.     packet.ipPtr = (Net_IPHeader *) (packet.dbase + sizeof(*packet.net.etherPtr));
  1103.     
  1104. #ifdef TEST_RANDOM_INPUT_LOST
  1105.     if ((random()&0x1) == 0) {
  1106.     printf("IP_PacketInput: Losing an input packet\n");
  1107.     status = FAILURE;
  1108.     goto exit;
  1109.     }
  1110. #endif
  1111. #ifdef TEST_DISCONNECT
  1112.    if (ips_Disconnect) {
  1113.     printf("IP_PacketInput: Losing an input packet\n");
  1114.     status = FAILURE;
  1115.     goto exit;
  1116.     }
  1117. #endif
  1118.     /*
  1119.      * PRIMITIVE ROUTING.  Snarf up the ethernet source address of
  1120.      * packets comming from hosts (1) that we want to know about.
  1121.      */
  1122.     if (Net_NetToHostInt(packet.ipPtr->source) == lookforIPAddress) {
  1123.     RteInsertAddress(lookforIPAddress,
  1124.         &NET_ETHER_HDR_SOURCE(*(Net_EtherHdr *) packet.dbase),
  1125.         NET_UPDATE_ADDR, infoPtr);
  1126.     lookforIPAddress = NET_INET_LOCAL_HOST;
  1127.     }
  1128.     status = IP_Input(netID, &packet);
  1129. exit:
  1130.     if (status != SUCCESS) {
  1131.     free(packet.base);
  1132.     }
  1133. }
  1134. #endif /* KERNEL */
  1135.  
  1136.  
  1137. /*
  1138.  *----------------------------------------------------------------------
  1139.  *
  1140.  * Rte_GetNetNum --
  1141.  *
  1142.  *    Returns the Internet network # for a route address specified
  1143.  *    by the argument.
  1144.  *
  1145.  * Results:
  1146.  *    An Internet network #.
  1147.  *
  1148.  * Side effects:
  1149.  *    None.
  1150.  *
  1151.  *----------------------------------------------------------------------
  1152.  */
  1153.  
  1154. unsigned int
  1155. Rte_GetNetNum(netID)
  1156.     Rte_NetID    netID;
  1157. {
  1158.     return(((NetInfo *)netID.net)->netPart);
  1159. }
  1160.  
  1161.  
  1162. /*
  1163.  *----------------------------------------------------------------------
  1164.  *
  1165.  * Rte_GetBroadcastAddr --
  1166.  *
  1167.  *    Returns the official Internet address for a route address specified
  1168.  *    by the argument.
  1169.  *
  1170.  * Results:
  1171.  *    An Internet address.
  1172.  *
  1173.  * Side effects:
  1174.  *    None.
  1175.  *
  1176.  *----------------------------------------------------------------------
  1177.  */
  1178.  
  1179. Net_InetAddress
  1180. Rte_GetBroadcastAddr(netID)
  1181.     Rte_NetID    netID;
  1182. {
  1183.     return(Net_HostToNetInt( ((NetInfo *)netID.net)->localBrdcastAddr ));
  1184. }
  1185.  
  1186.  
  1187. /*
  1188.  *----------------------------------------------------------------------
  1189.  *
  1190.  * Rte_GetSubnetMask --
  1191.  *
  1192.  *    Returns the official Internet address for the route address specified
  1193.  *    by the argument.
  1194.  *
  1195.  * Results:
  1196.  *    An Internet address.
  1197.  *
  1198.  * Side effects:
  1199.  *    None.
  1200.  *
  1201.  *----------------------------------------------------------------------
  1202.  */
  1203.  
  1204. unsigned int
  1205. Rte_GetSubnetMask(netID)
  1206.     Rte_NetID    netID;
  1207. {
  1208.     return(((NetInfo *)netID.net)->subnetMask);
  1209. }
  1210.  
  1211.  
  1212. /*
  1213.  *----------------------------------------------------------------------
  1214.  *
  1215.  * Rte_GetOfficialAddr --
  1216.  *
  1217.  *    Returns the official Internet (broadcast) address for this host.
  1218.  *
  1219.  * Results:
  1220.  *    An Internet address.
  1221.  *
  1222.  * Side effects:
  1223.  *    None.
  1224.  *
  1225.  *----------------------------------------------------------------------
  1226.  */
  1227.  
  1228. Net_InetAddress
  1229. Rte_GetOfficialAddr(broadcastWanted)
  1230.     Boolean     broadcastWanted;    /* If TRUE, return the official 
  1231.                      * broadcast address, else the
  1232.                      * official address. */
  1233. {
  1234.     if (broadcastWanted) {
  1235.     return(Net_HostToNetInt(netInfo[0].localBrdcastAddr));
  1236.     } else {
  1237.     return(Net_HostToNetInt(netInfo[0].address));
  1238.     }
  1239. }
  1240.  
  1241.  
  1242. /*
  1243.  *----------------------------------------------------------------------
  1244.  *
  1245.  * Rte_IsLocalAddr --
  1246.  *    Determines whether an address is local.
  1247.  *
  1248.  * Results:
  1249.  *    Returns TRUE if the address is on the local net (including different
  1250.  *    subnets), FALSE otherwise.
  1251.  *    
  1252.  *
  1253.  * Side effects:
  1254.  *    None.
  1255.  *
  1256.  *----------------------------------------------------------------------
  1257.  */
  1258.  
  1259. Boolean
  1260. Rte_IsLocalAddr(netID)
  1261.     Rte_NetID    netID;            /* Net identifier for remote host */
  1262. {
  1263.     register NetAddrInfo *addrPtr = (NetAddrInfo *)netID.host;
  1264.     int remoteNet = Net_HostToNetInt(addrPtr->inet) &
  1265.     ((NetInfo *)netID.net)->netMask;
  1266.     int localNet = Net_HostToNetInt(netInfo[0].address) & netInfo[0].netMask;
  1267.  
  1268.     return(remoteNet == localNet);
  1269. }
  1270.  
  1271.  
  1272. /*
  1273.  *----------------------------------------------------------------------
  1274.  *
  1275.  * Rte_IsBroadcastAddr --
  1276.  *
  1277.  *    Checks an Internet address to see if it's a broadcast address.
  1278.  *    There are two types of general broadcast addresses: the old style 
  1279.  *    (0.0.0.0) and the new style (255.255.255.255). In addition, 
  1280.  *    there are broadcast addresses for the local network: e.g.
  1281.  *    (128.32.0.0) and (128.32.255.255). If subnetting is in use,
  1282.  *    (128.32.150.0) and (128.32.150.255) are examples of subnet
  1283.  *    broadcast addresses using the old and new styles.
  1284.  *
  1285.  *    This depends on these various addresses having been installed.
  1286.  *
  1287.  * Results:
  1288.  *    TRUE    - it is a broadcast address.
  1289.  *    FALSE    - it is an address of a host.
  1290.  *
  1291.  * Side effects:
  1292.  *    None.
  1293.  *
  1294.  *----------------------------------------------------------------------
  1295.  */
  1296.  
  1297. Boolean
  1298. Rte_IsBroadcastAddr(address)
  1299.     Net_InetAddress    address;
  1300. {
  1301.     NetAddrInfo *addrPtr;
  1302.  
  1303.     address = Net_NetToHostInt(address);
  1304.     addrPtr = RteFetchAddress(address);
  1305.     if ((addrPtr != (NetAddrInfo *)NULL) && (addrPtr->flags & NET_BROADCAST)) {
  1306.     return(TRUE);
  1307.     }
  1308.     return(FALSE);
  1309. }
  1310.  
  1311.  
  1312. /*
  1313.  *----------------------------------------------------------------------
  1314.  *
  1315.  * GetLineList --
  1316.  *
  1317.  *    Reads in a group of lines delimited by startDelim and endDelim
  1318.  *    into arrayPtr. Each line in the array is stored in a separate 
  1319.  *    buffer that must be freed when it is no longer needed.
  1320.  *
  1321.  * Results:
  1322.  *    None.
  1323.  *
  1324.  * Side effects:
  1325.  *    Memory for the lines is allocated.
  1326.  *
  1327.  *----------------------------------------------------------------------
  1328.  */
  1329.  
  1330. #ifndef KERNEL
  1331. static void
  1332. GetLineList(stream, startDelim, endDelim, arraySize, arrayPtr, numLinesPtr)
  1333.     FILE    *stream;    /* Stream to read from. */
  1334.     char    *startDelim;    /* Starting delimiter, rest of line ignored. */
  1335.     char    *endDelim;    /* Ending delimiter, rest of line ignored. */
  1336.     int        arraySize;    /* Number of lines in arrayPtr. */
  1337.     char    **arrayPtr;    /* Array to store ptrs to each line. */
  1338.     int        *numLinesPtr;    /* Actual number of lines stored in arrayPtr.*/
  1339. {
  1340.     char     *linePtr;
  1341.     int        lineNum = -1;
  1342.  
  1343.     /*
  1344.      * Search for the start delimiter, ignoring the rest of the line.
  1345.      */
  1346.  
  1347.     linePtr = malloc(LINE_LEN+1);
  1348.     do {
  1349.     if (fgets(linePtr, LINE_LEN, stream) == NULL) {
  1350.         goto done;
  1351.     }
  1352.     } while (strncmp(startDelim, linePtr, strlen(startDelim)) != 0);
  1353.     /*
  1354.  
  1355.      * Now save all lines until the ending delimiter is seen.
  1356.      * Lines starting with # are not saved.
  1357.      */
  1358.  
  1359.     if (fgets(linePtr, LINE_LEN, stream) == NULL) {
  1360.     goto done;
  1361.     }
  1362.     while (strncmp(endDelim, linePtr, strlen(endDelim)) != 0) {
  1363.     if (linePtr[0] != COMMENT_CHAR) {
  1364.         lineNum++;
  1365.         if (lineNum == arraySize) {
  1366.         (void) fprintf(stderr, 
  1367.             "GetLineList: max num lines reached %d\n", arraySize);
  1368.         lineNum--;
  1369.         break;
  1370.         }
  1371.         arrayPtr[lineNum] = linePtr;
  1372.         linePtr = malloc(LINE_LEN+1);
  1373.     }
  1374.     if (fgets(linePtr, LINE_LEN, stream) == NULL) {
  1375.         break;
  1376.     }
  1377.     }
  1378.     /*
  1379.      * Free the line that contains the end delimiter.
  1380.      */
  1381. done:
  1382.     free(linePtr);
  1383.  
  1384.     *numLinesPtr = lineNum + 1;
  1385. }
  1386. #endif
  1387.